﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ThatsMeSDK;
using System.IO;
using System.Threading;
using System.Diagnostics;
using System.Net;

namespace ThatsMeBackUpWizard
{
    public partial class BackupWizard : Form
    {
        //TM UserName
        User user;
        string BackUpFolder = "";
        string delimiter = " - ";

        delegate void UpdateBackupStatus(string message);
        delegate void StopBackup();

        UpdateBackupStatus ubs;
        StopBackup sb;

        public BackupWizard()
        {
            InitializeComponent();
            pHeader.BringToFront();

            ubs = new UpdateBackupStatus(UpdateBackupStatusSafe);
            sb = new StopBackup(FinishBackupSafe);
        }

        private void UpdateBackupStatusSafe(string message)
        {
            this.lBackupStatus.Text = message;
        }

        private void FinishBackupSafe()
        {
            this.pbBackup.Style = ProgressBarStyle.Blocks;
            this.pbBackup.Value = 100;
            UpdateBackupStatusSafe("Backup has been finished!");
            this.btnNext.Enabled = true;
            this.btnBack.Enabled = true;
            this.btnCancel.Enabled = true;
        }

        private void tcContent_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.btnNext.Enabled = true;
            this.btnBack.Enabled = true;
            this.btnCancel.Enabled = true;

            switch (tcContent.SelectedTab.Name)
            {
                case "tpStart":
                    this.btnBack.Enabled = false;
                    break;
                case "tpLogin":
                    this.btnNext.Enabled = false;
                    break;
                case "tpBackup":
                    CheckBackupProps();
                    break;
                case "tpProcess":
                    this.btnNext.Enabled = false;
                    break;
                case "tpFinish":
                    this.btnNext.Enabled = false;
                    this.btnBack.Enabled = false;
                    break;
            }
        }

        private void CheckBackupProps()
        {
            if (this.user != null)
            {

            }
            else
            {
                MessageBox.Show("You have to login with your thats-me.ch account!", "Thats-Me Backup Wizard");
                btnBack_Click(new object(), new EventArgs());
            }
        }

        private void btnBack_Click(object sender, EventArgs e)
        {
            tcContent.SelectedIndex--;
        }

        private void btnNext_Click(object sender, EventArgs e)
        {
            tcContent.SelectedIndex++;
        }

        private void btnLogin_Click(object sender, EventArgs e)
        {
            //GUI funcs
            lLoginState.Text = "loggin in...";
            Cursor = Cursors.WaitCursor;
            Application.DoEvents();

            this.user = new User(this.tbUsername.Text, this.tbPassword.Text);
            if (this.user.LogIn())
            {
                lLoginState.Text = "successfully logged in!";
                this.btnNext_Click(sender, e);
            }
            else
            {
                lLoginState.Text = "username or password wrong!";
                this.user = null;
            }
            //GUI funcs
            Cursor = Cursors.Default;
            Application.DoEvents();
        }

        private void btnChooseFolder_Click(object sender, EventArgs e)
        {
            //Choose folder
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            fbd.Description = "Where are would you like to save your backup?";

            if (this.tbFolder.Text != string.Empty)
            {
                fbd.SelectedPath = this.tbFolder.Text;
            }

            if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.tbFolder.Text = fbd.SelectedPath;
            }
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnBackup_Click(object sender, EventArgs e)
        {
            if (Directory.Exists(this.tbFolder.Text))
            {
                this.btnNext.Enabled = false;
                this.btnBack.Enabled = false;
                this.btnCancel.Enabled = false;
                this.btnBackup.Enabled = false;

                this.BackUpFolder = this.tbFolder.Text;

                pProgress.Visible = true;

                Thread tBackup = new Thread(TMBackup);
                tBackup.Start();
            }
            else
            {
                MessageBox.Show("Select an existing folder, please!", "Thats-Me Backup Wizard");
                this.btnBack_Click(sender, e);
                Application.DoEvents();
            }
        }

        private void UpdateStatus(string message)
        {
            this.Invoke(ubs, new object[] {message});
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Process.Start(this.BackUpFolder);
        }

        //-------------------------------------------------- Backup Related Stuff -----------------------

        /// <summary>
        /// Backup all the tm related stuff
        /// </summary>
        private void TMBackup()
        {
            UpdateStatus("starting backup...");

            BackupProfileInfo();

            BackupFriendList();

            BackupImages();

            this.Invoke(sb);
        }

        private void BackupProfileInfo()
        {
            UpdateStatus("collecting profile info...");
            user.LoadMyUser();
            StringBuilder ptext = new StringBuilder();

            ptext.AppendLine("Id" + delimiter + user.Id);
            ptext.AppendLine("Nick" + delimiter + user.Nick);
            ptext.AppendLine("RealName" + delimiter + user.RealName);
            ptext.AppendLine("Birthday" + delimiter + user.Birthday.ToString());
            ptext.AppendLine("Canton" + delimiter + user.Canton.ToString());
            ptext.AppendLine("Sex" + delimiter + user.Sex.ToString());
            ptext.AppendLine("Friends" + delimiter + user.Friends.Count);
            ptext.AppendLine("ProfileUri" + delimiter + user.ProfileUri);
            ptext.AppendLine("Description:");
            ptext.AppendLine("");
            ptext.AppendLine(user.Description);
            
            UpdateStatus("saving profile info...");
            File.WriteAllText(BackUpFolder + "/profileinfo.txt", ptext.ToString());

            //download user image
            UpdateStatus("downloading profile image...");
            BitmapFromWeb(user.ProfilePictureUri).Save((BackUpFolder + "/profilepicture.jpg"));
        }

        private string CollectMember(Member m)
        {
            UpdateStatus("collecting profile info of " + m.Nick + "...");
            StringBuilder ptext = new StringBuilder();

            ptext.AppendLine("Id" + delimiter + m.Id);
            ptext.AppendLine("Nick" + delimiter + m.Nick);
            ptext.AppendLine("RealName" + delimiter + m.RealName);
            ptext.AppendLine("Birthday" + delimiter + m.Birthday.ToString());
            ptext.AppendLine("Canton" + delimiter + m.Canton.ToString());
            ptext.AppendLine("Sex" + delimiter + m.Sex.ToString());
            ptext.AppendLine("Friends" + delimiter + m.Friends.Count);
            ptext.AppendLine("ProfileUri" + delimiter + m.ProfileUri);
            ptext.AppendLine("Description:");
            ptext.AppendLine("");
            ptext.AppendLine(m.Description);

            UpdateStatus("saving profile info of " + m.Nick + "...");
            return ptext.ToString();
        }

        private void BackupFriendList()
        {
            UpdateStatus("collecting friendlist...");
            string friendfolder = BackUpFolder + "/friends";
            Directory.CreateDirectory(friendfolder);

            foreach (Member m in user.Friends)
            {
                File.WriteAllText(friendfolder + "/" + m.Nick + ".txt", CollectMember(m));
                UpdateStatus("downloading profile image of "+ m.Nick + "...");
                BitmapFromWeb(m.ProfilePictureUri).Save(friendfolder + "/" + CleanPath(m.Nick) + ".jpg");
            }
        }

        private void BackupImages()
        {
            UpdateStatus("collecting images...");
            string ifolder = BackUpFolder + "/images";
            Directory.CreateDirectory(ifolder);

            foreach (GalleryCategory cats in user.Categories)
            {
                UpdateStatus("collecting images in " + cats.Title + "...");
                string catfolder = ifolder + "/" + CleanPath(cats.Title);
                Directory.CreateDirectory(catfolder);

                foreach (GalleryPicture pic in cats.CategoryPictures)
                {
                    UpdateStatus("downloading image " + pic.SourceBig.ToString() + "...");
                    BitmapFromWeb(pic.SourceBig).Save(catfolder + "/" + pic.Id + ".jpg");
                }
            }
        }

        private string CleanPath(string path)
        {
            string invalid = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());

            foreach (char c in invalid)
            {
                path = path.Replace(c.ToString(), "");
            }

            return path;
        }

        /// <summary>
        /// Get a bitmap directly from the web
        /// </summary>
        /// <param name="URL">The URL of the image</param>
        /// <returns>A bitmap of the image requested</returns>
        public Bitmap BitmapFromWeb(Uri address)
        {
            try
            {
                // create a web request to the url of the image
                HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(address);
                // set the method to GET to get the image
                myRequest.Method = "GET";
                // get the response from the webpage
                HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
                // create a bitmap from the stream of the response
                Bitmap bmp = new Bitmap(myResponse.GetResponseStream());
                // close off the stream and the response
                myResponse.Close();
                // return the Bitmap of the image
                return bmp;
            }
            catch (Exception ex)
            {
                UpdateStatus("Error: " + ex.Message);
                return null;
            }
        }
    }
}
